/******************************************************************************* * Copyright (c) 2008, 2012 Innoopract Informationssysteme GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.rap.ui.internal.preferences; import java.io.IOException; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener; import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent; import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.internal.util.ParamCheck; import org.eclipse.rap.rwt.service.SettingStore; import org.eclipse.rap.rwt.service.SettingStoreEvent; import org.eclipse.rap.rwt.service.SettingStoreListener; import org.eclipse.ui.internal.WorkbenchPlugin; import org.osgi.service.prefs.Preferences; /** * This class is the link between the SessionPreferenceNode hierarchy * (application global) the RWT setting store (session specific). */ final class SessionPreferenceNodeCore { private final SessionPreferencesNode node; private ListenerList prefListeners; // ListenerList is thread safe private final ListenerList nodeListeners = new ListenerList( ListenerList.IDENTITY ); // thread safe /* tracks changes in RWT setting store and notifies the prefListeners */ private SettingStoreListener rwtListener; /* true to track RWT changes */ private boolean trackChanges = true; /* ignore changes to this key for a short time */ private String ignoreKey; SessionPreferenceNodeCore( final SessionPreferencesNode node ) { ParamCheck.notNull( node, "node" ); //$NON-NLS-1$ this.node = node; } void addPreferenceChangeListener( IPreferenceChangeListener listener ) { if( listener != null ) { getListenerList().add( listener ); setTrackRWTChanges( true ); } } void removePreferenceChangeListener( IPreferenceChangeListener listener ) { if( listener != null ) { ListenerList list = getListenerList(); list.remove( listener ); if( list.isEmpty() ) { setTrackRWTChanges( false ); } } } void firePreferenceEvent( final String key, final String oldValue, final String newValue ) { if( prefListeners != null ) { final PreferenceChangeEvent event = new PreferenceChangeEvent( node, key, oldValue, newValue ); Object[] listeners = prefListeners.getListeners(); for( int i = 0; i < listeners.length; i++ ) { final IPreferenceChangeListener listener = ( IPreferenceChangeListener )listeners[ i ]; ISafeRunnable op = new ISafeRunnable() { public void handleException( final Throwable exception ) { // logged by SafeRunner } public void run() throws Exception { listener.preferenceChange( event ); } }; SafeRunner.run( op ); } } } void clear() { if( prefListeners != null ) { prefListeners.clear(); prefListeners = null; setTrackRWTChanges( false ); } nodeListeners.clear(); } synchronized String put( final String uniqueKey, final String value ) { SettingStore store = RWT.getSettingStore(); String result = store.getAttribute( uniqueKey ); try { ignoreKey = uniqueKey; store.setAttribute( uniqueKey, value ); ignoreKey = null; } catch( IOException exception ) { String msg = "Could not persist preference: " + uniqueKey; //$NON-NLS-1$ WorkbenchPlugin.log( msg, exception ); } return result; } // helping methods ////////////////// private synchronized ListenerList getListenerList() { if( prefListeners == null ) { prefListeners = new ListenerList( ListenerList.IDENTITY ); } return prefListeners; } private synchronized void setTrackRWTChanges( final boolean doTrack ) { trackChanges = doTrack; if( trackChanges ) { if( rwtListener == null ) { rwtListener = new SettingStoreListener() { public void settingChanged( SettingStoreEvent event ) { if( trackChanges ) { String fullKey = event.getAttributeName(); if( !fullKey.equals( ignoreKey ) ) { String absPath = node.absolutePath(); if( fullKey.startsWith( absPath ) ) { String key = fullKey.substring( absPath.length() + 1 ); String oldValue = event.getOldValue(); String newValue = event.getNewValue(); firePreferenceEvent( key, oldValue, newValue ); } } } } }; } RWT.getSettingStore().addSettingStoreListener( rwtListener ); } else { // !trackChanges if( rwtListener != null ) { RWT.getSettingStore().removeSettingStoreListener( rwtListener ); } } } public void addNodeChangeListener( final INodeChangeListener listener ) { nodeListeners.add( listener ); } public void removeNodeChangeListener( final INodeChangeListener listener ) { nodeListeners.remove( listener ); } public void fireNodeEvent( final Preferences child, final boolean wasAdded, final SessionPreferencesNode spn ) { final NodeChangeEvent event = new NodeChangeEvent( spn, child ); Object[] listeners = nodeListeners.getListeners(); for( int i = 0; i < listeners.length; i++ ) { final INodeChangeListener listener = ( INodeChangeListener )listeners[ i ]; ISafeRunnable op = new ISafeRunnable() { public void handleException( final Throwable exception ) { // logged by SafeRunner } public void run() throws Exception { if( wasAdded ) { listener.added( event ); } else { listener.removed( event ); } } }; SafeRunner.run( op ); } } }